import { promises as fs } from 'fs';
import path from 'path';
import { fileURLToPath } from 'url';
import axios from 'axios';

// 在ES模块中获取__dirname
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Ollama配置
const OLLAMA_CONFIG = {
  baseURL: 'http://localhost:11434',
  model: 'qwen:7b',
  timeout: 30000,
};

// System prompt 定义 - 作为面试官的指南
const SYSTEM_PROMPT = `你是一位专业的就业成熟度评估面试官，请严格遵守以下规则：

1. 作为面试官，你需要对用户进行6个维度的评估：职业认知、专业技能、通用能力、求职技能、心理素质和环境适应。每个维度至少提问3个问题。

2. 所有提问要与用户指定的行业和职业相关，问题应该具有针对性和引导性，能够帮助全面了解用户在各维度的水平。

3. 提问语气要轻松、温和，营造舒适的对话氛围。避免使用过于专业或生硬的术语，让用户能够自然地表达自己的想法。

4. 当用户的回答偏离问题或答非所问时，需要用温和的方式引导用户回到问题本身，不要直接批评或否定用户。

5. 问题之间要有逻辑性，能够基于用户上一个回答自然过渡到下一个问题，形成连贯的对话流程。

6. 每次只提出一个问题，不要一次性提出多个问题，确保用户能够清晰理解并针对性回答。

7. 在生成回答时，严格按照指定的任务类型和输出格式要求进行，确保回答内容简洁明了、专业准确。`;

// 任务类型提示模板
const PROMPT_TEMPLATES = {
  // 解析用户输入的行业和职业
  'industry_profession_parse': {
    task: '请从用户输入中提取行业和职业信息，并以JSON格式输出。',
    format: '请严格按照{"industry": "行业名称", "profession": "职业名称"}的格式输出，不要包含其他内容。',
    example: '用户输入: "我想了解互联网行业的数据分析师"\n输出: {"industry": "互联网", "profession": "数据分析师"}'
  },
  
  // 检查回答是否相关
  'relevance_check': {
    task: '请检查用户回答是否与问题相关。',
    format: '请严格按照{"isRelevant": true或false}的格式输出，不要包含其他内容。',
    example: '问题: "你认为作为一名数据分析师需要具备哪些核心技能？"\n回答: "我喜欢编程。"\n输出: {"isRelevant": false}'
  },
  
  // 生成评估问题
  'question_generate': {
    task: '请根据给定的维度、行业和职业，生成一个针对性的评估问题。',
    format: '请直接输出问题内容，问题要具体、有针对性，并且以问号结尾。',
    example: '维度: 职业认知\n行业: 互联网\n职业: 数据分析师\n输出: 你对互联网行业中数据分析师岗位的主要工作职责了解多少？'
  },
  
  // 生成评估报告
  'report_generate': {
    task: '请根据对话历史，生成一份详细的就业成熟度评估报告。',
    format: '请生成一份结构化的Markdown格式报告，包含评估概述、维度分析、综合评估、等级评定和改进建议。',
    example: '# 就业成熟度评估报告\n\n## 评估概述\n- **评估行业**: 互联网\n- **评估职业**: 数据分析师\n- **评估时间**: 2024-01-01\n\n## 维度分析\n...'
  }
};

// 会话存储
let conversations = new Map();

// 知识库内容缓存
let knowledgeBaseContent = '';

/**
 * 初始化目录和加载知识库
 */
async function initialize() {
  try {
    // 确保必要的目录存在
    const knowledgeBaseDir = path.join(__dirname, '../knowledge_base');
    await fs.mkdir(knowledgeBaseDir, { recursive: true });
    
    // 加载知识库
    await loadKnowledgeBase();
    
    console.log('Model service initialized successfully');
  } catch (error) {
    console.error('Failed to initialize model service:', error.message);
  }
}

/**
 * 获取或创建会话
 * @param {string} conversationId 会话ID
 * @returns {object} 会话对象
 */
function getOrCreateConversation(conversationId) {
  if (!conversations.has(conversationId)) {
    conversations.set(conversationId, {
      id: conversationId,
      messages: [],
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString()
    });
  }
  
  return conversations.get(conversationId);
}

/**
 * 更新会话状态
 * @param {string} conversationId 会话ID
 * @param {object} stateUpdates 要更新的状态
 */
function updateConversationState(conversationId, stateUpdates) {
  const conversation = getOrCreateConversation(conversationId);
  
  // 更新会话状态
  Object.assign(conversation, stateUpdates);
  conversation.updatedAt = new Date().toISOString();
  
  conversations.set(conversationId, conversation);
}

/**
 * 添加消息到会话
 * @param {string} conversationId 会话ID
 * @param {string} role 角色（system, user, assistant）
 * @param {string} content 消息内容
 */
function addMessageToConversation(conversationId, role, content) {
  const conversation = getOrCreateConversation(conversationId);
  
  if (!conversation.messages) {
    conversation.messages = [];
  }
  
  conversation.messages.push({
    role,
    content,
    timestamp: new Date().toISOString()
  });
  
  // 更新会话
  conversations.set(conversationId, conversation);
}

/**
 * 构建提示词
 * @param {string} taskType 任务类型
 * @param {string} input 输入内容
 * @param {object} context 上下文信息
 * @returns {string} 构建好的提示词
 */
function buildPrompt(taskType, input, context = {}) {
  const template = PROMPT_TEMPLATES[taskType];
  
  if (!template) {
    throw new Error(`Unknown task type: ${taskType}`);
  }
  
  // 基础提示模板
  let prompt = `${SYSTEM_PROMPT}\n\n`;
  prompt += `任务: ${template.task}\n`;
  prompt += `格式要求: ${template.format}\n\n`;
  prompt += `示例:\n${template.example}\n\n`;
  
  // 添加上下文信息
  if (Object.keys(context).length > 0) {
    prompt += '上下文信息:\n';
    Object.entries(context).forEach(([key, value]) => {
      prompt += `- ${key}: ${value}\n`;
    });
    prompt += '\n';
  }
  
  // 添加用户输入
  if (input) {
    prompt += `用户输入: """${input}"""\n\n`;
  }
  
  prompt += '请根据以上要求生成输出:';
  
  return prompt;
}

/**
 * 生成模型响应
 * @param {string} prompt 提示词
 * @returns {Promise<string>} 模型响应
 */
async function generateResponse(prompt) {
  try {
    // 添加知识库内容到提示词
    const enhancedPrompt = knowledgeBaseContent ? 
      `${knowledgeBaseContent}\n\n${prompt}` : 
      prompt;
    
    // 调用Ollama API
    const response = await axios.post(
      `${OLLAMA_CONFIG.baseURL}/api/generate`,
      {
        model: OLLAMA_CONFIG.model,
        prompt: enhancedPrompt,
        stream: false,
      },
      {
        timeout: OLLAMA_CONFIG.timeout,
        headers: {
          'Content-Type': 'application/json',
        },
      }
    );
    
    // 提取响应内容
    const responseContent = response.data.response || '';
    
    // 清理JSON字符串
    return cleanJSONString(responseContent);
  } catch (error) {
    console.error('Error generating response:', error.message);
    
    // 返回默认响应
    return getDefaultResponse(prompt);
  }
}

/**
 * 生成聊天响应
 * @param {string} conversationId 会话ID
 * @param {string} userMessage 用户消息
 * @returns {Promise<string>} 模型响应
 */
async function generateChatResponse(conversationId, userMessage) {
  try {
    const conversation = getOrCreateConversation(conversationId);
    
    // 准备消息历史，只包含最近的对话上下文（避免过长历史导致的问题）
    // 最多保留最近5轮对话（10条消息）
    const messageHistory = conversation.messages || [];
    const recentMessages = messageHistory.slice(-10); // 只保留最近10条消息
    
    const messages = [
      { role: 'system', content: SYSTEM_PROMPT },
      ...recentMessages,
      { role: 'user', content: userMessage }
    ];
    
    // 调用Ollama API的聊天接口
    const response = await axios.post(
      `${OLLAMA_CONFIG.baseURL}/api/chat`,
      {
        model: OLLAMA_CONFIG.model,
        messages,
        stream: false,
      },
      {
        timeout: OLLAMA_CONFIG.timeout,
        headers: {
          'Content-Type': 'application/json',
        },
      }
    );
    
    // 提取响应内容
    const responseContent = response.data.message?.content || '';
    
    // 保存消息到会话
    addMessageToConversation(conversationId, 'user', userMessage);
    addMessageToConversation(conversationId, 'assistant', responseContent);
    
    return responseContent;
  } catch (error) {
    console.error('Error generating chat response:', error.message);
    
    // 返回默认响应
    return '抱歉，我暂时无法生成响应。请稍后再试。';
  }
}

/**
 * 加载知识库
 */
async function loadKnowledgeBase() {
  try {
    const knowledgeBaseDir = path.join(__dirname, '../knowledge_base');
    
    // 检查目录是否存在
    try {
      await fs.access(knowledgeBaseDir);
    } catch (e) {
      // 如果目录不存在，创建一个示例文件
      await fs.mkdir(knowledgeBaseDir, { recursive: true });
      
      const exampleContent = '# 就业成熟度评估知识库\n\n' +
        '## 评估维度说明\n\n' +
        '### 1. 职业认知\n' +
        '- 了解目标职业的职责范围、工作内容\n' +
        '- 理解职业发展路径和晋升机制\n' +
        '- 掌握行业发展趋势和市场需求\n\n' +
        '### 2. 专业技能\n' +
        '- 具备岗位要求的核心专业知识\n' +
        '- 掌握必要的工具和技术\n' +
        '- 有实践经验或项目经历\n\n' +
        '### 3. 通用能力\n' +
        '- 有效沟通和表达能力\n' +
        '- 团队协作和人际交往能力\n' +
        '- 问题解决和批判性思维\n\n' +
        '### 4. 求职技能\n' +
        '- 简历制作和优化能力\n' +
        '- 面试技巧和表现\n' +
        '- 求职渠道和资源获取\n\n' +
        '### 5. 心理素质\n' +
        '- 抗压能力和挫折应对\n' +
        '- 职业规划和目标设定\n' +
        '- 自我认知和定位\n\n' +
        '### 6. 环境适应\n' +
        '- 角色转换适应能力\n' +
        '- 工作环境和节奏适应\n' +
        '- 职场文化和人际关系处理\n';
      
      await fs.writeFile(
        path.join(knowledgeBaseDir, 'example.md'),
        exampleContent
      );
    }
    
    // 读取目录中的所有文件
    const files = await fs.readdir(knowledgeBaseDir);
    
    // 读取所有Markdown文件内容
    let content = '';
    for (const file of files) {
      if (file.endsWith('.md')) {
        const filePath = path.join(knowledgeBaseDir, file);
        const fileContent = await fs.readFile(filePath, 'utf8');
        content += fileContent + '\n\n';
      }
    }
    
    knowledgeBaseContent = content.trim();
    console.log(`Loaded knowledge base content from ${files.length} files`);
  } catch (error) {
    console.error('Failed to load knowledge base:', error.message);
    knowledgeBaseContent = '';
  }
}

/**
 * 清理JSON字符串
 * @param {string} jsonString JSON字符串
 * @returns {string} 清理后的字符串
 */
function cleanJSONString(jsonString) {
  // 移除可能的前缀和后缀
  let cleaned = jsonString.trim();
  
  // 移除代码块标记
  cleaned = cleaned.replace(/^```json|^```|```$/g, '').trim();
  
  // 移除可能的输出前缀
  cleaned = cleaned.replace(/^输出:\s*/, '').trim();
  
  return cleaned;
}

/**
 * 获取默认响应
 * @param {string} prompt 原始提示词
 * @returns {string} 默认响应
 */
function getDefaultResponse(prompt) {
  // 根据提示词类型返回不同的默认响应
  if (prompt.includes('industry_profession_parse')) {
    return '{"industry": "互联网", "profession": "软件工程师"}';
  } else if (prompt.includes('relevance_check')) {
    return '{"isRelevant": true}';
  } else if (prompt.includes('question_generate')) {
    return '能分享一下你在这方面的经历或想法吗？';
  } else {
    return '抱歉，我暂时无法生成详细内容。请稍后再试。';
  }
}

/**
 * 清理过期会话
 */
function cleanupExpiredConversations() {
  const now = new Date();
  const expiryTime = 24 * 60 * 60 * 1000; // 24小时
  
  for (const [conversationId, conversation] of conversations.entries()) {
    const lastUpdated = new Date(conversation.updatedAt);
    
    if (now - lastUpdated > expiryTime) {
      conversations.delete(conversationId);
      console.log(`Removed expired conversation: ${conversationId}`);
    }
  }
}

/**
 * 获取会话统计信息
 * @returns {object} 会话统计
 */
function getConversationStats() {
  return {
    activeConversations: conversations.size,
    timestamp: new Date().toISOString()
  };
}

/**
 * 保存调试信息
 * @param {string} type 调试类型
 * @param {string} content 调试内容
 */
async function saveDebugInfo(type, content) {
  try {
    const debugDir = path.join(__dirname, '../debug');
    await fs.mkdir(debugDir, { recursive: true });
    
    const fileName = `${type}_${Date.now()}.log`;
    const filePath = path.join(debugDir, fileName);
    
    await fs.writeFile(filePath, content, 'utf8');
    console.log(`Debug info saved: ${fileName}`);
  } catch (error) {
    console.error('Failed to save debug info:', error.message);
  }
}

// 初始化服务
initialize();

// 定期清理过期会话
setInterval(cleanupExpiredConversations, 60 * 60 * 1000); // 每小时清理一次

export {
  // 会话管理
  getOrCreateConversation,
  updateConversationState,
  addMessageToConversation,
  
  // 提示词构建
  buildPrompt,
  
  // 模型交互
  generateResponse,
  generateChatResponse,
  
  // 知识库管理
  loadKnowledgeBase,
  
  // 工具函数
  cleanJSONString,
  getDefaultResponse,
  
  // 统计和维护
  getConversationStats,
  cleanupExpiredConversations,
  
  // 调试
  saveDebugInfo
};
